package com.zhangmeng.tools.controller;

import cn.hutool.core.text.StrFormatter;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.zhangmeng.tools.dto.BeanField;
import com.zhangmeng.tools.dto.GenerateDetail;
import com.zhangmeng.tools.utils.AlertUtils;
import com.zhangmeng.tools.utils.TemplateUtil;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.util.Callback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.CollectionUtils;

import javax.sound.sampled.Port;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author : 芊芊墨客
 * @version : 1.0
 * @date : 2023-03-22 14:03
 */
@Slf4j
public class MybatisPlusGenerator {

    @FXML
    public TextField url;

    @FXML
    public TextField username;

    @FXML
    public TextField password;

    @FXML
    public TextField author;

    @FXML
    public TextField out_dir;

    @FXML
    public TextField prefix;

    @FXML
    public TextField mapper_xml_path;

    @FXML
    public TextField model_name;

    @FXML
    public TextField parent_package;

    @FXML
    public Button generator;

    @FXML
    private TextField port;

    @FXML
    private ComboBox<String> comboBox_data_base;

    @FXML
    private TextField data_base;

    @FXML
    public ListView<String> listView;

    private final ObservableList<String> data_base_list = FXCollections.observableArrayList();
    private final ObservableList<String> table_list = FXCollections.observableArrayList();

    private JdbcTemplate jdbcTemplate;

    @FXML
    public void initialize() {

        if (url.getText().length() == 0) {
            url.setText("localhost");
        }

        if (username.getText().length() == 0) {
            username.setText("root");
        }

        if (port.getText().length() == 0) {
            port.setText("3306");
        }

        if (password.getText().length() == 0) {
            password.setText("root");
        }

        if (author.getText().length() == 0) {
            author.setText("zhangmeng");
        }

        if (out_dir.getText().length() == 0) {
            out_dir.setText("D:\\mybatis_gen");
        }

        if (prefix.getText().length() == 0) {
            prefix.setText("dashidao,t");
        }

        if (mapper_xml_path.getText().length() == 0) {
            mapper_xml_path.setText("D:\\mybatis_gen\\mapper");
        }

        if (model_name.getText().length() == 0) {
            model_name.setText("server");
        }

        if (parent_package.getText().length() == 0) {
            parent_package.setText("com.zhangmeng");
        }

        comboBox_data_base.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue != null) {
                log.info("选择的数据库名为:{}", newValue);
                data_base.setText(newValue);
                update_select_data_base();
            }
        });

        listView.setItems(table_list);
        listView.setFixedCellSize(40);
        listView.getSelectionModel().select(0);
        listView.setCellFactory(new Callback<>() {
            @Override
            public ListCell<String> call(ListView<String> param) {
                return new ListCell<>() {
                    @Override
                    protected void updateItem(String item, boolean empty) {
                        super.updateItem(item, empty);
                        if (!empty) {
                            HBox hBox = new HBox();
                            hBox.setAlignment(Pos.CENTER);
                            hBox.getChildren().add(new Label(item));
                            this.setGraphic(hBox);
                        }
                    }
                };
            }
        });

        generator.setOnAction(event -> {

            String ur1 = getUrl(url.getText(), Integer.parseInt(port.getText()), data_base.getText());
            DataSourceInfo dataSourceInfo = new DataSourceInfo();
            dataSourceInfo.setUrl(ur1);
            dataSourceInfo.setUsername(username.getText());
            dataSourceInfo.setPassword(password.getText());
            dataSourceInfo.setAuthor(author.getText());
            dataSourceInfo.setOut_dir(out_dir.getText());
            dataSourceInfo.setParent_package_name(parent_package.getText());
            dataSourceInfo.setParent_module_name(model_name.getText());
            dataSourceInfo.setMapper_xml_path(mapper_xml_path.getText());
            String text = prefix.getText();
            String[] prefixes = text.split(",");
            dataSourceInfo.setTable_prefixes(prefixes);
            List<String> tables = new ArrayList<>(table_list);
            dataSourceInfo.setTables(tables);
            generator(dataSourceInfo);
            AlertUtils.alert_msg("生成成功!");
        });
    }

    @FXML
    public void get_all_data_base() {
        log.info("获取所有数据表.....");
        data_base_list.clear();
        getJdbcTemplate();
        List<Map<String, Object>> maps = this.jdbcTemplate.queryForList("show databases");
        for (Map<String, Object> map : maps) {
            log.info("map->{}", map.toString());
            data_base_list.add(map.get("Database").toString());
        }
        comboBox_data_base.setItems(data_base_list);
        comboBox_data_base.getSelectionModel().select(0);
        data_base.setText(comboBox_data_base.getSelectionModel().getSelectedItem());
    }

    @FXML
    public void fetch_table() {
        table_list.clear();
        getJdbcTemplate();
        List<Map<String, Object>> maps = this.jdbcTemplate.queryForList("SELECT table_name, table_type, TABLE_COMMENT FROM information_schema.tables WHERE table_schema =  (select database()) ORDER BY table_name DESC");
        for (Map<String, Object> map : maps) {
            String table_name = (String) map.get("table_name");
            log.info("table_name:{}", table_name);
            table_list.add(table_name);
        }
    }

    private void update_select_data_base() {
        String text = data_base.getText();
        getJdbcTemplate();
        log.info("update_select_data_base:{}", text);
        this.jdbcTemplate.execute("use `" + text + "`");
    }

    public String getUrl(String ip, int port, String data_base) {
        return StrFormatter.format("jdbc:mysql://{}:{}/{}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true", ip, port, data_base);
    }

    public void generator(DataSourceInfo dataSourceInfo) {
        FastAutoGenerator.create(dataSourceInfo.getUrl(), dataSourceInfo.getUsername(), dataSourceInfo.getPassword()).globalConfig(builder -> {
                    builder.author(dataSourceInfo.author) // 设置作者
//                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir(dataSourceInfo.getOut_dir()); // 指定输出目录
                }).packageConfig(builder -> {
                    builder.parent(dataSourceInfo.getParent_package_name()) // 设置父包名
                            .moduleName(dataSourceInfo.getParent_module_name()) // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, dataSourceInfo.getMapper_xml_path())); // 设置mapperXml生成路径
                }).strategyConfig(builder -> {
                    builder.addInclude(dataSourceInfo.getTables()) // 设置需要生成的表名
                            .addTablePrefix(dataSourceInfo.getTable_prefixes())
                            .enableCapitalMode()
                            .entityBuilder()
                            .idType(IdType.AUTO)
                            .enableChainModel()
                            .enableLombok()
                            .enableRemoveIsPrefix()
                            .enableTableFieldAnnotation()
                            .enableActiveRecord()
                            .controllerBuilder()
                            .enableRestStyle()
                            .build();
                }).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板，默认的是Velocity引擎模板
                .execute();
    }

    public JdbcTemplate getJdbcTemplate() {

        if (jdbcTemplate == null) {
            jdbcTemplate = new JdbcTemplate();

            DruidDataSource datasource = new DruidDataSource();
            String con = "jdbc:mysql://" + url.getText() + ":" + port.getText() + "/" + data_base.getText() + "?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true";
            String driverClassName = "com.mysql.jdbc.Driver";
            datasource.setUrl(con);
            datasource.setUsername(username.getText());
            datasource.setPassword(password.getText());
            datasource.setDriverClassName(driverClassName);

            jdbcTemplate.setDataSource(datasource);
        }
        return jdbcTemplate;
    }

    public static class DataSourceInfo {

        public DataSourceInfo() {
        }

        public DataSourceInfo(String url, String username, String password, String author, String out_dir, String parent_package_name, String parent_module_name, String mapper_xml_path, List<String> tables, String[] table_prefixes) {
            this.url = url;
            this.username = username;
            this.password = password;
            this.author = author;
            this.out_dir = out_dir;
            this.parent_package_name = parent_package_name;
            this.parent_module_name = parent_module_name;
            this.mapper_xml_path = mapper_xml_path;
            this.tables = tables;
            this.table_prefixes = table_prefixes;
        }

        private String url;
        private String username;
        private String password;
        private String author;
        private String out_dir;
        private String parent_package_name;
        private String parent_module_name;//设置父包模块名
        private String mapper_xml_path;//设置mapperXml生成路径;

        private List<String> tables;//表名

        private String[] table_prefixes;

        public String[] getTable_prefixes() {
            return table_prefixes;
        }

        public void setTable_prefixes(String[] table_prefixes) {
            this.table_prefixes = table_prefixes;
        }

        public List<String> getTables() {
            return tables;
        }

        public void setTables(List<String> tables) {
            this.tables = tables;
        }

        public String getMapper_xml_path() {
            return mapper_xml_path;
        }

        public void setMapper_xml_path(String mapper_xml_path) {
            this.mapper_xml_path = mapper_xml_path;
        }

        public String getParent_module_name() {
            return parent_module_name;
        }

        public void setParent_module_name(String parent_module_name) {
            this.parent_module_name = parent_module_name;
        }

        public String getParent_package_name() {
            return parent_package_name;
        }

        public void setParent_package_name(String parent_package_name) {
            this.parent_package_name = parent_package_name;
        }

        public String getOut_dir() {
            return out_dir;
        }

        public void setOut_dir(String out_dir) {
            this.out_dir = out_dir;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public String getAuthor() {
            return author;
        }

        public void setAuthor(String author) {
            this.author = author;
        }
    }

}
